﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

using MathTools;

namespace ChartTools
{
    public partial class ChartCanvas : Control
    {
        #region Fields

        double[ , ] m_points;
        bool m_showLine;

        #endregion
        public ChartCanvas()
        {
        }

        public void SetPoints( double[,] points, bool showLine )
        {
            m_points = points;
            m_showLine = showLine;

       //     Refresh();
        }

        protected override void OnResize( EventArgs e )
        {
            base.OnResize( e );

            Refresh();
        }

        protected override void OnSizeChanged( EventArgs e )
        {
            Refresh();
        }

        protected override void OnPaint( PaintEventArgs e )
        {
            if( m_points == null )
                return;

            try
            {
                const int margin = 100;
                int count = m_points.GetLength( 1 );

                int width = this.Width;
                int height = this.Height;

                Graphics g = e.Graphics;
                g.Clear( Color.White );

                double maxX = m_points[ 0, count - 1 ];
                double minX = m_points[ 0, 0 ];

                double maxY = double.MinValue;
                double minY = double.MaxValue;

                for( int i = 0; i < count; i++ )
                {
                    for( int j = 1; j < m_points.GetLength( 0 ); j++ )
                    {
                        double value = m_points[ j, i ];

                        if( Double.IsInfinity( value ) )
                            continue;

                        if( maxY < value )
                            maxY = value;

                        if( minY > value )
                            minY = value;
                    }
                }

                maxY += 0.1 * Math.Abs( maxY );
                minY -= 0.1 * Math.Abs( minY );

                double scaleY = ( height - 2 * margin ) / ( maxY - minY + 1 );

                double scaleX = ( width - 2 * margin ) / ( maxX - minX );

                g.DrawLine( Pens.Black, new Point( margin, height - margin ), new Point( margin, margin ) );
                g.DrawLine( Pens.Black, new Point( margin, height - margin ), new Point( width - margin, height - margin ) );

                g.DrawString( maxX.ToString(), this.Font, Brushes.Blue, new PointF( width - margin, height - margin - 10 ) );

                g.DrawString( minY.ToString(), this.Font, Brushes.Blue, new PointF( margin, height - margin ) );
                g.DrawString( maxY.ToString(), this.Font, Brushes.Blue, new PointF( margin, margin ) );

                if( count > 0 )
                {
                    int visualStep = count / 1000 + 1;
                    for( int d = 1; d < m_points.GetLength( 0 ); d++ )
                    {
                        Pen drawPen;

                        switch( d )
                        {
                            case 1:
                                drawPen = Pens.Green;
                                break;
                            case 2:
                                drawPen = Pens.Red;
                                break;
                            default:
                                drawPen = Pens.BlueViolet;
                                break;
                        }

                        double prevX = m_points[ 0, 0 ];
                        double prevY = m_points[ d, 0 ];

                        for( int i = 1; i < count; i += visualStep )
                        {
                            double newX = m_points[ 0, i ];
                            double newY = m_points[ d, i ];

                            g.DrawLine( drawPen,
                                new Point( ( int )( prevX * scaleX - minX + margin ), ( int )( prevY * scaleY + margin ) ),
                                new Point( ( int )( newX * scaleX - minX + margin ), ( int )( newY * scaleY + margin ) ) );

                            prevX = newX;
                            prevY = newY;
                        }
                    }

                }
            }
            catch( Exception )
            {
                ;
            }

        }
    }
}
